package com.bjpowernode.service.impl;

import com.bjpowernode.bean.Product;
import com.bjpowernode.dao.ProductDao;
import com.bjpowernode.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductDao dao;

    @Autowired
    private RedisTemplate<Object, Object> rt;

    @Override
    public Double findTurnover() {
        // 获取Redis指定key的操作对象
        BoundValueOperations<Object, Object> ops = rt.boundValueOps("turnover");
        // 从缓存中读取指定key的value
        Object turnover = ops.get();

        // 使用双重检测锁机制预防缓存击穿
        // 若缓存中没有该数据，则先从DB中查询，然后再写入到缓存
        if (turnover == null) {
            synchronized (this) {
                turnover = ops.get();
                if (turnover == null) {
                    // 获取当前日期，并格式化
                    Date date = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    turnover = dao.selectTurnover(sdf.format(date));

                    // 将查询结果写入到缓存
                    ops.set(turnover, 10, TimeUnit.SECONDS);
                }
            }
        }

        return (Double) turnover;
    }

    @Override
    @Cacheable(value = "pc", key = "'product_all'")
    public List<Product> findAllProducts() {
        return dao.selectAllProducts();
    }

    @Override
    @Cacheable(value = "pc", key = "'product_'+#name")
    public List<Product> findProductsByName(String name) {
        return dao.selectProductsByName(name);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "pc", allEntries = true)   // 只要该方法被执行，立即清除pc缓存中的所有数据
    public void saveProduct(Product product) {
        dao.insertProduct(product);
    }
}
